<?php
/**
 * @name       DataSet
 * @access     public
 * @author     Marcos Vinicius Pereira dos Santos, <marcos@eagletecnologia.com>
 * @version    1.0
 * @package    PHPJasperReport
 * @subpackage Core
 * @since      1.0
 */
class DataSet {
    /**
     * @access public
     * @var String
     */
    public $name = "Default";

    /**
     * @access public
     * @var String
     */
    public $sql = "";

    /**
     * @access private
     * @var Array
     */
    private $dbConfig = null;

    /**
     * @access private
     * @var PDOStatement
     */
    private $data = null; 

    /**
     * @access public
     * @var Array
     */
    public $parameters = array();

    /**
     * @access public
     * @var Array
     */
    public $variables = array();

    /**
     * @access public
     * @var Array
     */
    public $record = null;

    /**
     * @access public
     * @var Pattern
     */
    private $pattern = null;

    public function  __construct() {
        $this->pattern = new Pattern();
        $this->initVariables();
    }

    /**
     * @access private
     */
    private function initVariables(){
        $this->variables['PAGE_NUMBER'] = new Variable();        
        
        $this->variables['COLUMN_NUMBER'] = new Variable();

        $this->variables['REPORT_COUNT'] = new Variable();
        $this->variables['REPORT_COUNT']->calculation = 'COUNT';
        $this->variables['REPORT_COUNT']->incrementType = 'REPORT';
        $this->variables['REPORT_COUNT']->value = 0;

        $this->variables['PAGE_COUNT'] = new Variable();
        $this->variables['PAGE_COUNT']->calculation = 'COUNT';
        $this->variables['PAGE_COUNT']->incrementType = 'PAGE';
        $this->variables['PAGE_COUNT']->value = 0;

        $this->variables['COLUMN_COUNT'] = new Variable();
        $this->variables['COLUMN_COUNT']->calculation = 'COUNT';
        $this->variables['COLUMN_COUNT']->incrementType = 'COLUMN';
        $this->variables['COLUMN_COUNT']->value = 0;
    }

    /**
     * @access public
     * @param array $dbConfig
     */
    public function setDBConfig(Array $dbConfig){
        $this->dbConfig = $dbConfig;
    }

    /**
     * @access public
     * @param  Array $parameters
     */
    public function setParameters($parameters){
        if(!empty($this->parameters)){            
            foreach($this->parameters as $key => $value){
                if(array_key_exists($key, $parameters)){
                    $this->parameters[$key] = $parameters[$key];
                }
            }
        }
    }

    /**
     * Método responsável por preparar a query sql para ser executada na base
     * de dados. Em outras palavras, este método realiza a substituição dos
     * parâmentros pelos valores correspondentes.
     *
     * @access private
     * @return String
     */
    private function prepareSQL(){

        if(isset($this->parameters)){
            foreach($this->parameters as $key => $value){
                $sql = str_replace('$P{'.$key.'}', $value, $this->sql);
            }
        }
        return $sql;
    }

    /**
     * @access public
     */
    public function loadData(){
        if(!empty ($this->sql)){
            $dataBase = DataBase::getDataBase($this->dbConfig);

            $db = $dataBase->prepare($this->prepareSQL() );

            if($db->execute()){
                $this->data = $db;
            }
        }else{
            throw new Exception("Não existe comando SQL!");
        }
    }

    /**
     * @access public
     * @return Boolean
     */
    public function nextRecord(){
        $returnValue = false;

        if($this->data){
            if($this->record = $this->data->fetch(PDO::FETCH_ASSOC)){
                $returnValue = true;
                $this->updateVariables();
            }
        }

        return $returnValue;
    }

    /**
     * @access public
     * @return Boolean
     */
    public function hasData(){
        if($this->data){
            return ($this->data->rowCount() > 0)?true:false;
        }else{
            return false;
        }
    }

    /**
     * @access public
     * @param String $expression
     * @return Mixed
     */
    public final function getValueExpression($expression){
        $return = $expression;
        
        //echo $expression."<br/>";
        if(!ereg('{|[0-9]+:|^[0-9]+|^[0-9]+[\.\,][0-9]+', $expression)){            
            eval("\$return = ".$expression.";");
            //echo $return."<br/>";
            $return = utf8_encode($return);
        }

        return $return;
    }

    /**
     * @access private
     * @param  String $variableName
     * @param  stdClass $variable
     * @return Float
     */
    private function sum($variableName,$variable){

        if($this->fields[$variableName]->class == "TIME"){
            $returnValue = Util::sumTime($variable->value, $this->getValueExpression($variable->variableExpression));
        }else{
            $returnValue = $variable->value + $this->getValueExpression($variable->variableExpression);
        }

        return $returnValue;
    }

    /**
     * @access public
     */
    public function updateVariables(){
        if($this->variables) {
            foreach($this->variables as $key => $variable) {
                switch($variable->calculation) {
                    case "COUNT":                        
                        $this->variables[$key]->value = ++$variable->value;
                        break;
                    case "DISTINCT COUNT":
                        break;
                    case "SUM":
                        $this->variables[$key]->value = $this->sum($key,$variable);
                        break;
                    case "AVERAGE":
                        break;
                    case "LOWEST":
                        break;
                    case "HIGHEST":
                        break;
                    case "STANDARD DEVIATION":
                        break;
                }
            }
        }
    }

    /**
     * @access public
     * @param  String $resetType
     * @param  String $nameGroup
     * @return void
     */
    public function resetVariables($resetType,$nameGroup = ""){
        $resetType = strtoupper($resetType);
        $nameGroup = strtoupper($nameGroup);

        if($this->variables) {
            foreach ($this->variables as $key => $variable) {

                if($variable->resetType == $resetType && $variable->resetGroup == $nameGroup) {

                    $this->variables[$key]->value = $variable->initialValueExpression;
                }
            }
        }
    }
}
?>
